package vip.lsjscl.flowboot.workflow.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import vip.lsjscl.flowboot.common.BusinessException;
import vip.lsjscl.flowboot.util.DKBeanUtil;
import vip.lsjscl.flowboot.util.UserInfoHolder;
import vip.lsjscl.flowboot.util.constants.*;
import vip.lsjscl.flowboot.workflow.entity.DKActivity;
import vip.lsjscl.flowboot.workflow.entity.DKRuntimeTask;
import vip.lsjscl.flowboot.workflow.entity.DKTransition;
import vip.lsjscl.flowboot.workflow.entity.DKWorkflowVersion;
import vip.lsjscl.flowboot.workflow.handler.DKActivityHandler;
import vip.lsjscl.flowboot.workflow.handler.DKGatewayHandler;
import vip.lsjscl.flowboot.workflow.model.Node;
import vip.lsjscl.flowboot.workflow.model.dto.ProcessDataDto;
import vip.lsjscl.flowboot.workflow.repository.DKActivityRepository;
import vip.lsjscl.flowboot.workflow.repository.DKRuntimeTaskRepository;
import vip.lsjscl.flowboot.workflow.repository.DKTransitionRepository;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 活动服务类
 * <p>
 * 提供获取下一个活动的方法，考虑当一个活动后继有多个活动时，通过变迁条件进行判断
 *
 * @author
 * @date 2025/02/13
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class DKActivityService {
    private final UserInfoHolder userInfoHolder;

    private final DKRuntimeTaskRepository runtimeTaskRepository;

    private final DKRuntimeTaskService runtimeTaskService;

    private final ApplicationContext applicationContext;

    private final DKActivityRepository activityRepository;

    private final DKTransitionRepository transitionRepository;

    private final DKTransitionService transitionService;


    /**
     * 根据决策更新办件记录的当前活动节点：
     * 如果决策为 "APPROVED"，则激活下一个活动；
     * 如果决策为 "RETURN_PREVIOUS"，则激活上一个活动；
     * 如果决策为 "RETURN_APPLICANT"，则退回到第一个活动；
     * 如果决策为 "DISAPPROVED"，则流程停止，不创建新的任务记录。
     */
    public void updateCurrentTaskActivity(ProcessDataDto processDataDto) {
        String currentUserId = userInfoHolder.getCurrentUserId();
        String currentDeptId = userInfoHolder.getCurrentDeptId();
        String taskId = String.valueOf(processDataDto.getId());
        DKRuntimeTask currentTask = runtimeTaskRepository.findByIdAndStatus(taskId, TaskStatus.PENDING);
        DKActivity activity = currentTask.getActivity();
        List<String> approvers = activity.getApprovers();
        List<String> departments = activity.getDepartments();

        if (!CollectionUtils.isEmpty(approvers) || !CollectionUtils.isEmpty(departments)) {
            boolean includeCurrentUser = !CollectionUtils.isEmpty(approvers) && approvers.contains(currentUserId);
            boolean includeCurrentDept = !CollectionUtils.isEmpty(departments) && departments.contains(currentDeptId);
            //如果两个都没有包含，则抛出异常
            if (!includeCurrentUser && !includeCurrentDept) {
                throw new BusinessException("当前用户没有权限审批此任务");
            }
        }

        String businessId = currentTask.getBusinessId();
        List<DKActivity> newActivityList = new ArrayList<>();

        TaskDecision decision = processDataDto.getAction();
        switch (decision) {
            case APPROVED:
                if (StringUtils.isEmpty(processDataDto.getNextNodeId())) {
                    newActivityList = getNextActivity(activity);
                }
                else {
                    newActivityList.add(activityRepository.findById(processDataDto.getNextNodeId()).get());
                }
                currentTask.setStatus(TaskStatus.COMPLETED);
                activity.setStatus(ActivityStatus.COMPLETED);
                break;
            case RETURN_PREVIOUS:
                if (StringUtils.isEmpty(processDataDto.getPrevNodeId())) {
                    newActivityList = transitionService.getFromActivity(activity, true);
                }
                else {
                    newActivityList.add(activityRepository.findById(processDataDto.getPrevNodeId()).get());
                }

                currentTask.setStatus(TaskStatus.BACK_PREVIOUS);
                activity.setStatus(ActivityStatus.BACK_PREVIOUS);
                break;
            case RETURN_APPLICANT:
                //获取开始节点
                DKActivity startActivity = getStartActivity(currentTask.getWorkflowVersionId(), businessId);
                newActivityList = getNextActivity(startActivity);
                //获取第一个活动节点
                currentTask.setStatus(TaskStatus.RETURNED);
                activity.setStatus(ActivityStatus.RETURNED);
                break;
            case DISAPPROVED:
                currentTask.setStatus(TaskStatus.TERMINATED);
                currentTask.setUpdateTime(LocalDateTime.now());
                runtimeTaskRepository.save(currentTask);
                activity.setStatus(ActivityStatus.TERMINATED);
                return;
            default:
                throw new BusinessException("未知决策: " + decision);
        }
        currentTask.setComment(processDataDto.getComment());
        currentTask.setProcessorId(userInfoHolder.getCurrentUserId());
        runtimeTaskRepository.save(currentTask);
        activityRepository.save(activity);
        // 执行活动节点的后置处理
        ((DKActivityService) AopContext.currentProxy()).executeActivityAfterClass(currentTask);

        // 设置下一个活动的审批人
        newActivityList.forEach(
                newActivity -> {
                    if (!CollectionUtils.isEmpty(processDataDto.getNextApprovers())) {
                        newActivity.setApprovers(processDataDto.getNextApprovers());
                    }
                    if (!CollectionUtils.isEmpty(processDataDto.getNextDepartments())) {
                        newActivity.setDepartments(processDataDto.getNextDepartments());
                    }
                }
        );

        // 激活下个活动
        ((DKActivityService) AopContext.currentProxy()).activateNextActiveNode(activity, newActivityList);
    }


    /**
     * 获取开始节点
     *
     * @return 第一个活动
     */
    public DKActivity getStartActivity(String workflowVersionId, String businessId) {
        // 根据流程版本id查询所有变迁记录
        List<DKActivity> activityList = activityRepository.findAllByNameAndWorkflowVersionIdAndBusinessId("开始", workflowVersionId, businessId);
        return activityList.get(0);
    }

    /**
     * 创建活动节点
     */
    public void createActivity(Node node, DKWorkflowVersion version, String businessId, Map<String, DKActivity> activityMap) {
        try {
            DKActivity activity = new DKActivity();
            activity.setNodeId(node.getId());
            activity.setWorkflowVersionId(version.getId());
            activity.setBusinessId(businessId);
            activity.setType(ActivityType.valueOf(node.getType()));
            activity.setName(node.getLabel());
            if (ActivityType.valueOf(node.getType()) == ActivityType.start) {
                activity.setStatus(ActivityStatus.COMPLETED);
            }
            if (node.getData() != null && StringUtils.isNotBlank(node.getData().getName())) {
                activity.setName(node.getData().getName());
                activity.setCode(node.getData().getCode());
                if (StringUtils.isNotBlank(node.getData().getExecutionLogic())) {
                    activity.setExecutionLogic(ExecutionLogic.valueOf(node.getData().getExecutionLogic()));
                }
                activity.setPageUrl(node.getData().getPageUrl());
                activity.setBeforeClass(node.getData().getBeforeClass());
                activity.setAfterClass(node.getData().getAfterClass());
                activity.setApprovers(node.getData().getApprovers());
                activity.setDepartments(node.getData().getDepartments());
                activity.setOperations(node.getData().getOperations());
            }

            DKActivity savedActivity = activityRepository.save(activity);
            activityMap.put(node.getId(), savedActivity);

            if (ActivityType.cc.name().equals(node.getType())) {
                DKRuntimeTask runtimeTask = new DKRuntimeTask();
                runtimeTask.setActivity(savedActivity);
                runtimeTask.setBusinessId(businessId);
                runtimeTask.setStatus(TaskStatus.COMPLETED);
                runtimeTask.setWorkflowVersionId(version.getId());
                runtimeTaskRepository.save(runtimeTask);
                ((DKActivityService) AopContext.currentProxy()).executeActivityBeforeClass(savedActivity);
            }
        }
        catch (Exception e) {
            log.error("Error creating activity: " + e.getMessage());
            throw new BusinessException("Error creating activity: " + e.getMessage());
        }
    }

    /**
     * 获取下一个活动节点
     *
     * @param currentActivity 当前活动
     * @return 下一个活动节点列表
     */
    public List<DKActivity> getNextActivity(DKActivity currentActivity) {
        List<DKTransition> transitions = transitionRepository.findAllByFromActivity(currentActivity);
        if (CollectionUtils.isEmpty(transitions)) {
            return new ArrayList<>();
        }

        // 按优先级分组并降序排列
        Map<Integer, List<DKTransition>> priorityGroups = transitions.stream()
                .collect(Collectors.groupingBy(
                        DKTransition::getPriority,
                        () -> new TreeMap<>(Comparator.reverseOrder()),
                        Collectors.toList()
                ));

        // 按优先级从高到低依次检查每个分组
        for (Map.Entry<Integer, List<DKTransition>> entry : priorityGroups.entrySet()) {
            List<DKTransition> group = entry.getValue();

            List<DKActivity> validActivities = group.stream()
                    .filter(transitionService::evaluateTransitionCondition)
                    .map(DKTransition::getToActivity)
                    .collect(Collectors.toList());

            if (!validActivities.isEmpty()) {
                // 返回第一个满足条件的优先级分组
                return validActivities;
            }
        }
        // 所有优先级分组都不满足条件
        return new ArrayList<>();
    }

    /**
     * 激活下一个活动节点和变迁 (启动工作流时用)
     *
     * @param currentActivity 当前活动
     */
    public void activateStartNodeAndTransition(DKActivity currentActivity) {
        DKRuntimeTask currentRuntimeTask = new DKRuntimeTask();
        currentRuntimeTask.setActivity(currentActivity);
        currentRuntimeTask.setBusinessId(currentActivity.getBusinessId());
        currentRuntimeTask.setStatus(TaskStatus.COMPLETED);
        currentRuntimeTask.setProcessorId(userInfoHolder.getCurrentUserId());
        currentRuntimeTask.setWorkflowVersionId(currentActivity.getWorkflowVersionId());
        runtimeTaskRepository.save(currentRuntimeTask);

        currentActivity.setStatus(ActivityStatus.COMPLETED);
        currentActivity.setApprovers(List.of(userInfoHolder.getCurrentUserId()));
        activityRepository.save(currentActivity);

        List<DKActivity> nextActivity = getNextActivity(currentActivity);
        if (!CollectionUtils.isEmpty(nextActivity)) {
            // 激活变迁
            transitionService.activateTransition(currentActivity, nextActivity);
            // 激活下一个节点
            nextActivity.forEach(activity -> {
                ((DKActivityService) AopContext.currentProxy()).executeActivityBeforeClass(activity);
                activity.setStatus(ActivityStatus.PENDING);
                activityRepository.save(activity);
            });
        }

        // 创建并保存运行时任务
        runtimeTaskService.createInitialRuntimeTask(nextActivity);
    }

    /**
     * 激活下个活动节点(审核时用)
     *
     * @param nextActivityList 下一个活动节点列表
     */
    public void activateNextActiveNode(DKActivity currentActivity, List<DKActivity> nextActivityList) {
        if (currentActivity == null || CollectionUtils.isEmpty(nextActivityList)) {
            return;
        }

        for (DKActivity nextActivity : nextActivityList) {
            if (nextActivity == null) {
                continue;
            }

            // 处理非网关和非结束节点
            if (!isGatewayOrEnd(nextActivity)) {
                ((DKActivityService) AopContext.currentProxy()).processNormalActivity(nextActivity);
            }

            // 处理网关节点
            if (nextActivity.getType() == ActivityType.gateway) {
                ((DKActivityService) AopContext.currentProxy()).processGatewayActivity(nextActivity);
            }

            //处理结束节点
            if (nextActivity.getType() == ActivityType.end) {
                nextActivity.setStatus(ActivityStatus.COMPLETED);
            }

            activityRepository.save(nextActivity);
        }

        // 修复点：使用实际生效的节点列表
        transitionService.activateTransition(currentActivity, nextActivityList);
    }

    public void processNormalActivity(DKActivity nextActivity) {
        if (nextActivity.getExecutionLogic() == ExecutionLogic.ANY) {
            runtimeTaskService.createInitialRuntimeTask(List.of(nextActivity));
            ((DKActivityService) AopContext.currentProxy()).executeActivityBeforeClass(nextActivity);
            nextActivity.setStatus(ActivityStatus.PENDING);
        }
        else if (nextActivity.getExecutionLogic() == ExecutionLogic.ALL) {
            ((DKActivityService) AopContext.currentProxy()).checkAllPredecessorsCompleted(nextActivity);
        }
    }

    /**
     * 检查已完成所有前置任务
     *
     * @param activity 活动
     */
    public void checkAllPredecessorsCompleted(DKActivity activity) {
        List<DKTransition> incoming = transitionService.getIncomingTransitions(activity);
        boolean allCompleted = incoming.stream()
                .map(DKTransition::getFromActivity)
                .allMatch(a -> a.getStatus() == ActivityStatus.COMPLETED);

        if (allCompleted) {
            runtimeTaskService.createInitialRuntimeTask(List.of(activity));
            ((DKActivityService) AopContext.currentProxy()).executeActivityBeforeClass(activity);
            activity.setStatus(ActivityStatus.PENDING);
        }
    }

    /**
     * 处理 Gateway 活动
     *
     * @param gateway 网关
     */
    public void processGatewayActivity(DKActivity gateway) {
        ExecutionLogic logic = gateway.getExecutionLogic();
        boolean shouldProcess = false;

        if (logic == ExecutionLogic.ANY) {
            shouldProcess = true;
        }
        else if (logic == ExecutionLogic.ALL) {
            shouldProcess = transitionService.getIncomingTransitions(gateway).stream()
                    .map(DKTransition::getFromActivity)
                    .allMatch(a -> a.getStatus() == ActivityStatus.COMPLETED);
        }

        if (shouldProcess) {
            gateway.setStatus(ActivityStatus.COMPLETED);
            List<DKActivity> nextActivities = getNextActivity(gateway);
            ((DKActivityService) AopContext.currentProxy()).activateNextActiveNode(gateway, nextActivities);
            activityRepository.save(gateway);
            // 执行活动节点的后置处理
            ((DKActivityService) AopContext.currentProxy()).executeGatewayAfterClass(gateway);
        }
    }

    /**
     * 是网关还是结束
     *
     * @param activity 活动
     * @return boolean
     */
    public boolean isGatewayOrEnd(DKActivity activity) {
        return activity.getType() == ActivityType.gateway || activity.getType() == ActivityType.end;
    }

    /**
     * 获取下一步可选的活动节点
     *
     * @param currentActivity 当前活动节点
     * @param businessId      业务ID
     * @return 下一步可选的活动节点列表
     */
    public List<DKActivity> getNextActivities(DKActivity currentActivity, String businessId) {
        // 获取所有从当前节点出发的变迁
        List<DKTransition> transitions = transitionService.getOutgoingTransitions(currentActivity);

        // 过滤出符合条件的变迁
        return transitions.stream()
                .filter(transition -> {
                    // 如果变迁有条件类，则执行条件判断
                    if (transition.getConditionClass() != null) {
                        try {
                            // TODO: 实现条件判断逻辑
                            // 这里需要根据实际情况实现条件判断
                            return true;
                        }
                        catch (Exception e) {
                            return false;
                        }
                    }
                    return true;
                })
                .map(DKTransition::getToActivity)
                .collect(Collectors.toList());
    }

    /**
     * 执行活动节点的后置处理
     */
    private void executeActivityBeforeClass(DKActivity activity) {
        if (activity != null && StringUtils.isNotBlank(activity.getAfterClass())) {
            try {
                Class<?> beanName = DKBeanUtil.getBeanName(activity.getAfterClass());
                DKActivityHandler handler = (DKActivityHandler) applicationContext.getBean(beanName);
                handler.beforeHandle(activity);
            }
            catch (Exception e) {
                throw new BusinessException("执行活动后置处理失败: " + e.getMessage());
            }
        }
    }

    /**
     * 执行活动节点的后置处理
     */
    private void executeGatewayAfterClass(DKActivity activity) {
        if (activity != null && StringUtils.isNotBlank(activity.getAfterClass())) {
            try {
                Class<?> beanName = DKBeanUtil.getBeanName(activity.getAfterClass());
                DKGatewayHandler handler = (DKGatewayHandler) applicationContext.getBean(beanName);
                handler.afterHandle(activity);
            }
            catch (Exception e) {
                throw new BusinessException("执行活动后置处理失败: " + e.getMessage());
            }
        }
    }


    /**
     * 执行活动节点的后置处理
     */
    private void executeActivityAfterClass(DKRuntimeTask runtimeTask) {
        if (runtimeTask != null && StringUtils.isNotBlank(runtimeTask.getActivity().getAfterClass())) {
            try {
                Class<?> beanName = DKBeanUtil.getBeanName(runtimeTask.getActivity().getAfterClass());
                DKActivityHandler handler = (DKActivityHandler) applicationContext.getBean(beanName);
                handler.afterHandle(runtimeTask);
            }
            catch (Exception e) {
                throw new BusinessException("执行活动后置处理失败: " + e.getMessage());
            }
        }
    }

    //判断流程是否初始化
    public Long isProcessInitialized(String businessId) {
        return runtimeTaskRepository.countByBusinessId(businessId);
    }

    /**
     * 获取最近一次退回申请人的节点
     *
     * @param businessId 业务id
     * @return {@link List }<{@link DKActivity }>
     */
    public DKActivity getReturnActivity(String businessId) {
        return activityRepository.findFirstByBusinessIdAndStatusOrderByUpdateTimeDesc(businessId, ActivityStatus.RETURNED);
    }
}